package com.cpit.platform.web.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

import com.cpit.platform.common.entity.TableDataQueryCondition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cpit.platform.common.constant.SystemConstant;
import com.cpit.platform.common.entity.Result;
import com.cpit.platform.common.entity.TableJsonData;
import com.cpit.platform.common.entity.ZTreeNode;
import com.cpit.platform.dao.SubSystemRepository;
import com.cpit.platform.dao.SystemModuleRepository;
import com.cpit.platform.dto.Authority;
import com.cpit.platform.dto.SubSystem;
import com.cpit.platform.dto.SystemModule;
import com.cpit.platform.log.LogOperator;
import com.cpit.platform.service.AuthorityService;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

@Controller
@RequestMapping(value = "/authority")
public class AuthController {

	@Autowired
	private AuthorityService authorityService;
	
	@Autowired
	private SystemModuleRepository systemModuleRepository;
	
	@Autowired
	private SubSystemRepository subSystemRepository;
	
	private final String loggerName = this.getClass().getName();
	
	@ApiOperation(value="查询权限列表", notes="通过条件查询系统中的权限信息" + 
	"支持分页查询，支持模糊查询。")
	@ResponseBody
	@PreAuthorize("hasAuthority('queryAuthority')")//有queryAuthority权限的才能访问  
	@RequestMapping(value="/queryAuthority", method = RequestMethod.GET)  
	public List<Authority> queryAuthority(
			@ApiParam(value = "当前页数， 以1开始。"  )  @RequestParam(value = "page", required = true, defaultValue = "1") int page, 
			@ApiParam(value = "当前页的内容长度。"  )  @RequestParam(value = "size", required = true, defaultValue = "20") int size, 
			@ApiParam(value = "排序方式：asc为升序，desc为降序。"  )  @RequestParam(value = "order", required = false, defaultValue = "asc") String order, 
			@ApiParam(value = "排序字段，与dto中声明的字段名称一致。"  )  @RequestParam(value = "orderBy", required = false, defaultValue = "id") String orderBy, 
			@ApiParam(value = "模糊搜索的字符串，根据权限的名称字段进行模糊匹配。"  )  @RequestParam(value = "pattern", required = false, defaultValue = "") String pattern) {
		return authorityService.findByCondition(page, size, order, orderBy, pattern);
	}  
	
	@ApiOperation(value="查询权限列表", notes="通过条件查询系统中的权限信息" + 
			"支持分页查询，支持模糊查询。")
		    @ApiImplicitParams({
		            @ApiImplicitParam(name = "cond", value = "JqGrid的条件对象，由JqGrid根据js参数自动封装。", required = true, dataType = "TableDataQueryCondition")
		    })
	@SuppressWarnings("rawtypes")
	@ResponseBody
	@PreAuthorize("hasAuthority('queryAuthority')")//有queryAuthority权限的才能访问  
	@RequestMapping(value="/queryAuthorityJqg", method = RequestMethod.GET)  
	public TableJsonData queryAuthorityJqg(TableDataQueryCondition cond) {
		TableJsonData tjd = authorityService.findByConditionJqg(cond);
		return tjd;
	}  
	
	@ApiOperation(value="创建权限项目", notes="用户手工指定权限项目并创建，" + 
			"需要手动输入权限的详细信息，包括名称、描述以及在子系统中的模块ID，鉴权标识等等。")
		     @ApiImplicitParam(name = "auth", value = "权限描述对象。", required = true, dataType = "Authority")
	@ResponseBody
	@PreAuthorize("hasAuthority('createAuthority')")//有createAuthority权限的才能访问  
	@RequestMapping(value="/createAuthority", method = RequestMethod.POST)  
	public Result<Authority> createAuthority(@RequestBody Authority auth) {
		try{
			authorityService.createAuthority(auth);
			return new Result<Authority>(Result.CODE_SUCCESS, "", auth);
		} catch(Exception e) {
			return new Result<Authority>(Result.CODE_FAILED, "", auth);
		}
	}  
	
	@ApiOperation(value="修改权限项目", notes="用户手工指定权限项目并修改，" + 
			"需要手动输入权限的详细信息，包括名称、描述以及在子系统中的模块ID，鉴权标识等等。")
		     @ApiImplicitParam(name = "auth", value = "权限描述对象。", required = true, dataType = "Authority")
	@ResponseBody
	@PreAuthorize("hasAuthority('modifyAuthority')")
	@RequestMapping(value="/modifyAuthority", method = RequestMethod.POST)  
	public Result<Authority> modifyAuthority(@RequestBody Authority auth) {
		try{
			authorityService.createAuthority(auth);
			return new Result<Authority>(Result.CODE_SUCCESS, "", auth);
		} catch(Exception e) {
			return new Result<Authority>(Result.CODE_FAILED, "", auth);
		}
	}
	
	@ApiOperation(value="删除权限项目", notes="在系统中删除已经存在的权限项目，" + 
			"如果该权限被角色引用，则不允许删除。")
		     @ApiImplicitParam(name = "auth", value = "权限描述对象。", required = true, dataType = "Authority")
	@ResponseBody
	@PreAuthorize("hasAuthority('deleteAuthority')")
	@RequestMapping(value="/deleteAuthority", method = RequestMethod.DELETE)  
	public Result<Authority> deleteAuthority(@RequestBody Authority auth) {
		try{
			authorityService.deleteAuthority(auth);
			return new Result<Authority>(Result.CODE_SUCCESS, "", auth);
		} catch(Exception e) {
			return new Result<Authority>(Result.CODE_FAILED, "", auth);
		}
	}  
	
	@ApiOperation(value="查询权限树", notes="获取全部权限的树，用于角色授权使用。")
	@ResponseBody
	@PreAuthorize("hasAuthority('queryAuthority')") 
	@RequestMapping(value="/getAuthorityTree", method = RequestMethod.GET)  
	public ZTreeNode getAuthorityTree() {
		List<Authority> allAuth = authorityService.findByCondition(1, 10000, SystemConstant.DIRECTION_ASC, "id", "");
		List<SystemModule> allMods = systemModuleRepository.findAll();
		TreeMap<String, TreeMap<String, List<Authority>>> authmap = new TreeMap<String, TreeMap<String, List<Authority>>>();
		for(Authority au : allAuth) {
			String subSId = au.getSystemId().toString();
			String modId = au.getModuleId().toString();
			TreeMap<String, List<Authority>> moduleMap = null;
			List<Authority> auLst = null;
			if(authmap.containsKey(subSId)) {
				moduleMap = authmap.get(subSId);
			} else {
				moduleMap = new TreeMap<String, List<Authority>>();
				authmap.put(subSId, moduleMap);
			}
			if(moduleMap.containsKey(modId)) {
				auLst = moduleMap.get(modId);
			} else {
				auLst = new ArrayList<Authority>();
				moduleMap.put(modId, auLst);
			}
			auLst.add(au);
		}
		
		ZTreeNode rootNode = new ZTreeNode("0", "-1", "所有权限", true, ZTreeNode.NODE_TYPE_GROUP);
		// set styles
		
		Set<String> sysSet = authmap.keySet();
		SubSystem sysDto = null;
		
		for(String sys : sysSet) {
			sysDto = getSubSystem(sys);
			if(sysDto == null) {
				continue;
			}
			ZTreeNode sysNode = new ZTreeNode(sys, "0", sysDto.getName(), true, ZTreeNode.NODE_TYPE_GROUP);
			// set styles
			
			rootNode.getChildren().add(sysNode);
			TreeMap<String, List<Authority>> modMap = authmap.get(sys);
			Set<String> modSet = modMap.keySet();
			SystemModule modDto = null;
			for(String mod : modSet) {
				modDto = getModuleDto(mod);
				ZTreeNode modNode = new ZTreeNode(mod, sys, modDto.getName(), true, ZTreeNode.NODE_TYPE_GROUP);
				// set style
				
				sysNode.getChildren().add(modNode);
				List<Authority> authLst = modMap.get(mod);
				for( Authority au : authLst) {
					ZTreeNode auNode = new ZTreeNode(au.getId().toString(), mod, au.getName(), true, ZTreeNode.NODE_TYPE_AUTH);
					// set style
					
					modNode.getChildren().add(auNode);
				}
			}
			
		}
		LogOperator.debug(loggerName, "get auth tree:\n" + rootNode);
		return rootNode;
	}  
	
	public SystemModule getModuleDto(String id) {
		return systemModuleRepository.findByModuleId(id);
	}
	
	public SubSystem getSubSystem(String id) {
		SubSystem s = null;
		if( id.equals(String.valueOf(SystemConstant.PLATFORM_ID)) ) {
			s = new SubSystem();
			s.setCode(String.valueOf(SystemConstant.PLATFORM_ID));
			s.setName("集成平台");
		} else {
			subSystemRepository.findById(Integer.parseInt(id));
		}
		return s;
	}
}
